package com.ecarx.camera.worker.camera.dvr;

import android.location.Location;
import android.widget.Toast;

import androidx.lifecycle.Observer;

import com.ecarx.camera.R;
import com.ecarx.camera.constant.Constants;
import com.ecarx.camera.constant.DvrStateDesc;
import com.ecarx.camera.data.ThumbnailData;
import com.ecarx.camera.ui.camera.ICameraUI;
import com.ecarx.camera.utils.LogUtils;
import com.ecarx.camera.worker.camera.ICameraWorker;
import com.ecarx.camera.worker.config.ConfigManager;
import com.ecarx.camera.worker.config.OnVideoMutedChangedListener;
import com.ecarx.camera.worker.event.DvrEvent;
import com.ecarx.camera.worker.event.RecordingTimerEvent;
import com.jeremyliao.liveeventbus.LiveEventBus;
import com.jeremyliao.liveeventbus.utils.AppUtils;

public class DvrCameraWorker implements ICameraWorker, OnVideoMutedChangedListener {

    private static final String TAG = "DvrCameraWorker";

    private ICameraUI mCameraUI;

    private Observer<DvrEvent.CaptureResultEvent> mCaptureResultEvent = new Observer<DvrEvent.CaptureResultEvent>() {
        @Override
        public void onChanged(DvrEvent.CaptureResultEvent captureEvent) {
            LogUtils.d(TAG, "onChanged CaptureResultEvent success:" + captureEvent.success);
            if (mCameraUI != null) {
                mCameraUI.updateOnPictureTaken(captureEvent.success);
            }
        }
    };

    private Observer<DvrEvent.RecordingStartedEvent> mRecordingStartedEvent = new Observer<DvrEvent.RecordingStartedEvent>() {
        @Override
        public void onChanged(DvrEvent.RecordingStartedEvent recordingStartedEvent) {
            LogUtils.d(TAG, "onChanged RecordingStartedEvent recordingType:" + (recordingStartedEvent.recordingType == Constants.DvrRecordingType.GENERAL ? "GENERAL" : "EMERGENCY"));
            if (mCameraUI == null) {
                return;
            }
            if (Constants.DvrRecordingType.EMERGENCY == recordingStartedEvent.recordingType) {
                mCameraUI.showVideoRecordingIndicator(true);
                mCameraUI.setVideoRecordingButtonEnable(false);
            } else {
                mCameraUI.updateOnVideoRecordingStarted();
            }
        }
    };

    private Observer<DvrEvent.RecordingEndedEvent> mRecordingEndedEvent = new Observer<DvrEvent.RecordingEndedEvent>() {
        @Override
        public void onChanged(DvrEvent.RecordingEndedEvent recordingEndedEvent) {
            LogUtils.d(TAG, "onChanged RecordingStartedEvent recordingType:" + (recordingEndedEvent.recordingType == Constants.DvrRecordingType.GENERAL ? "GENERAL" : "EMERGENCY"));
            if (mCameraUI == null) {
                return;
            }
            if (Constants.DvrRecordingType.EMERGENCY == recordingEndedEvent.recordingType) {
                mCameraUI.showVideoRecordingIndicator(false);
                mCameraUI.setVideoRecordingButtonEnable(true);
            } else {
                mCameraUI.updateOnVideoTaken(recordingEndedEvent.success);
            }
            if (!recordingEndedEvent.success) {
                // TODO: 2023/7/17 录制失败是否需要toast提示
            }
        }
    };

    private Observer<RecordingTimerEvent> mRecordingTimerEvent = new Observer<RecordingTimerEvent>() {
        @Override
        public void onChanged(RecordingTimerEvent recordingTimerEvent) {
            if (Constants.FacingType.EXTERIOR == recordingTimerEvent.facingType) {
                if (mCameraUI != null) {
                    mCameraUI.setVideoRecordingTimeText(recordingTimerEvent.hours, recordingTimerEvent.minutes, recordingTimerEvent.seconds);
                }
            }
        }
    };

    private Observer<DvrEvent.DvrStateErrorEvent> mDvrStateErrorEvent = new Observer<DvrEvent.DvrStateErrorEvent>() {

        @Override
        public void onChanged(DvrEvent.DvrStateErrorEvent dvrStateErrorEvent) {
            LogUtils.d(TAG, "onChanged DvrStateErrorEvent:" + (dvrStateErrorEvent.isErrorState ? " errorState:" + dvrStateErrorEvent.dvrErrorState : " normal"));
            if (mCameraUI == null) {
                return;
            }
            if (dvrStateErrorEvent.isErrorState) {
                String stateStr = AppUtils.getApp().getString(DvrStateDesc.getDvrStateStringResId(dvrStateErrorEvent.dvrErrorState));
                switch (dvrStateErrorEvent.dvrErrorState) {
                    case DvrEvent.DvrErrorState.DVR_STATE_CAMERA_CONNECTION_LOST:
                    case DvrEvent.DvrErrorState.DVR_STATE_VIDEO_RECORD_FAILURE:
                        // 显示错误页面
                        mCameraUI.showErrorLay(stateStr);
                        break;
                    default:
                        // 隐藏错误页面，也不需要toast提醒用户
                        mCameraUI.hideErrorLay();
                        break;
                }
            } else {
                mCameraUI.hideErrorLay();
            }
        }
    };

    private IDvrAPI.IDvrConfigWatcher mDvrConfigWatcher = new IDvrAPI.IDvrConfigWatcher() {
        @Override
        public void onDvrGeneralRecordResolutionChanged(int resolution) {
            LogUtils.d(TAG, "onDvrGeneralRecordResolutionChanged, resolution:" + resolution);
        }

        @Override
        public void onDvrGeneralRecordDurationChanged(int duration) {
            LogUtils.d(TAG, "onDvrGeneralRecordDurationChanged, duration:" + duration);
        }

        @Override
        public void onDvrGeneraRecordMicMuteChanged(boolean mute) {
            LogUtils.d(TAG, "onDvrGeneraRecordMicMuteChanged, mute:" + mute);
            ConfigManager.getInstance().setExteriorVideoMuted(mute, false);
            if (mCameraUI != null) {
                mCameraUI.setVideoMutedChecked(mute);
            }
        }

        @Override
        public void onDvrSdcardUsedPercentageChanged(int percentage) {
            LogUtils.d(TAG, "onDvrSdcardUsedPercentageChanged, percentage:" + percentage);
        }
    };

    @Override
    public void init() {
        DvrManager.get().registerDvrConfigWatcher(mDvrConfigWatcher);
    }

    @Override
    public void bindUI(ICameraUI cameraUI) {
        mCameraUI = cameraUI;
        if (cameraUI != null) {
            LiveEventBus.get(DvrEvent.CaptureResultEvent.class).observe(cameraUI.getFragment(), mCaptureResultEvent);
            LiveEventBus.get(DvrEvent.RecordingStartedEvent.class).observe(cameraUI.getFragment(), mRecordingStartedEvent);
            LiveEventBus.get(DvrEvent.RecordingEndedEvent.class).observe(cameraUI.getFragment(), mRecordingEndedEvent);
            LiveEventBus.get(DvrEvent.DvrStateErrorEvent.class).observe(cameraUI.getFragment(), mDvrStateErrorEvent);
            LiveEventBus.get(RecordingTimerEvent.class).observe(cameraUI.getFragment(), mRecordingTimerEvent);
        }
    }

    @Override
    public void doOnResume() {
        LogUtils.d(TAG, "doOnResume");
        onExteriorVideoMutedChanged(ConfigManager.getInstance().isExteriorVideoMuted());
        ConfigManager.getInstance().addOnVideoMutedChangedListener(this);

        if (mCameraUI != null) {
            mCameraUI.showVideoRecordingIndicator(DvrManager.get().isDvrEmergencyRecording() || DvrManager.get().isDvrGeneralRecording());
            mCameraUI.setVideoMutedChecked(ConfigManager.getInstance().isExteriorVideoMuted());
            mCameraUI.updateVideoRecordingButton(DvrManager.get().isDvrGeneralRecording());
            mCameraUI.setVideoRecordingButtonEnable(!DvrManager.get().isDvrEmergencyRecording());
        }
    }

    @Override
    public void doOnPause() {
        LogUtils.d(TAG, "doOnPause");
        ConfigManager.getInstance().removeOnVideoMutedChangedListener(this);
    }

    @Override
    public void doOnDestroy() {
        LogUtils.d(TAG, "doOnDestroy");
        DvrManager.get().unregisterDvrConfigWatcher(mDvrConfigWatcher);
    }

    @Override
    public void setCameraLocation(Location location) {
    }

    @Override
    public void setCameraZoom(float zoomRatio) {
    }

    @Override
    public void setVideoMode(boolean isVideoMode) {
    }

    @Override
    public void setUsePhotoTimerCountdown(boolean usePhotoTimerCountdown) {
    }

    @Override
    public void setUseVideoTimelapseMode(boolean useVideoTimelapseMode) {
    }

    @Override
    public boolean setCameraAudioMuted(boolean isMuted) {
        return ConfigManager.getInstance().setExteriorVideoMuted(isMuted);
    }

    @Override
    public void doCapture() {
        if (mCameraUI != null) {
            mCameraUI.updateOnPhotoTakingStarted();
        }
        DvrManager.get().doCapture();
    }

    @Override
    public void startRecordVideo() {
        DvrManager.get().startGeneralRecord();
    }

    @Override
    public void stopRecordVideo() {
        DvrManager.get().pauseGeneralRecord();
    }

    @Override
    public ThumbnailData getLatestThumbnail() {
        return DvrManager.get().getDvrLatestThumbnail();
    }

    @Override
    public void onInteriorVideoMutedChanged(boolean videoMuted) {
    }

    @Override
    public void onExteriorVideoMutedChanged(boolean videoMuted) {
        DvrManager.get().setDvrGeneralRecordMicMute(videoMuted);
    }

    /**
     * 判断当前TfCard是否存在
     * @return
     */
    public boolean checkDvrSdcardExists() {
        if (DvrManager.get().isDvrSdcardExists()) {
            return true;
        }
        Toast.makeText(AppUtils.getApp(), R.string.please_insert_tf_card, Toast.LENGTH_LONG).show();
        return false;
    }

}
